﻿using DataMgr.msg;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace DataMgr.File
{
    class FileBdf
    {
        private FileStream m_fileRW = null;
        private BDFHead m_head = new BDFHead();
        private int m_nLogCount = 0;
        //反序列化,得到类、结构体
        public static object RawDeserialize(byte[] rawdatas, Type anytype)
        {
            int rawsize = Marshal.SizeOf(anytype);
            if (rawsize > rawdatas.Length)
                return null;

            IntPtr buffer = Marshal.AllocHGlobal(rawsize);
            Marshal.Copy(rawdatas, 0, buffer, rawsize);
            object retobj = Marshal.PtrToStructure(buffer, anytype); 
            Marshal.FreeHGlobal(buffer);
            return retobj;
        }

        //序列化，结构体转化为流
        public static byte[] RawSerialize(object obj)
        {
            int rawsize = Marshal.SizeOf(obj);
            IntPtr buffer = Marshal.AllocHGlobal(rawsize);
            Marshal.StructureToPtr(obj, buffer, false);
            byte[] rawdatas = new byte[rawsize];
            Marshal.Copy(buffer, rawdatas, 0, rawsize);
            Marshal.FreeHGlobal(buffer);

            return rawdatas;
        }

        public bool CreateFile(string file)
        {
            m_fileRW = new FileStream(file, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            if (m_fileRW.Length > Marshal.SizeOf(m_head))//Marshal.SizeOf(typeof(BDFHead)
            {
                byte[] bytData = new byte[Marshal.SizeOf(m_head)];
                m_fileRW.Read(bytData, 0, bytData.Length);
                m_head = (BDFHead)RawDeserialize(bytData, typeof(BDFHead)); 
            }

            return m_fileRW.CanWrite;
        }

        //写文件头.
        public int WriteHead()
        {
            m_head.btFlag = Encoding.ASCII.GetBytes("_GLLL_");
            m_head.btDate = Encoding.ASCII.GetBytes(DateTime.Now.ToString("yyyyMMdd"));
            m_head.usVersion = (ushort)BDF_Version.BDF_Ver3;
            m_head.usNdaVer = (ushort)BDF_Version.BDF_Ver3;

            m_head.piChannelInfo.lluStart = (UInt64)Marshal.SizeOf(typeof(BDFHead));
            m_head.piChannelInfo.lluLen = (UInt64)Marshal.SizeOf(typeof(ChannelDeviceInfo));

            //工步数据
            m_head.piStepsData.lluStart = m_head.piChannelInfo.lluStart + m_head.piChannelInfo.lluLen;

            //记录数据
            m_head.piRecordsInfo.lluStart = m_head.piStepsData.lluStart + m_head.piStepsData.lluLen;

            //日志信息
            m_head.piLogsInfo.lluStart = m_head.piRecordsInfo.lluStart + m_head.piRecordsInfo.lluLen;
            m_head.piLogsInfo.lluLen = (UInt64)(Marshal.SizeOf(typeof(SingleHisLogData)) * m_nLogCount);

            //循环统计
            m_head.piCycle1.lluStart = m_head.piLogsInfo.lluStart + m_head.piLogsInfo.lluLen;
            //m_head.piCycle1.lluLen = m_cyclesCycleID.size() * sizeof(stNdaXCycle);

            //工步统计
            m_head.piStepsInfo.lluStart = m_head.piCycle1.lluStart + m_head.piCycle1.lluLen;
            //m_head.piStepsInfo.lluLen = m_steps.size() * sizeof(STEP_STATIS);

            m_fileRW.Seek(0, SeekOrigin.Begin);
            byte[] bytData = RawSerialize(m_head);
            m_fileRW.Write(bytData, 0, bytData.Length);
            return bytData.Length;
        }

        //写通道信息
        public int WriteChlInfo(ChannelDeviceInfo chlInfo)
        {
            m_fileRW.Seek((long)m_head.piChannelInfo.lluStart, SeekOrigin.Begin);
            byte[] bytData = RawSerialize(chlInfo);
            m_fileRW.Write(bytData, 0, bytData.Length);
            m_fileRW.Flush();
            return bytData.Length;
        }

        //写工步文件
        public int WriteStepFile(string file)
        {
            FileStream fs = new FileStream(file, FileMode.Open);
            byte[] bytData = new byte[fs.Length];
            fs.Read(bytData, 0, bytData.Length);
            fs.Close();

            m_head.piStepsData.lluLen = (UInt64)bytData.Length;

            WriteHead();

            m_fileRW.Seek((long)m_head.piStepsData.lluStart, SeekOrigin.Begin);
            m_fileRW.Write(bytData, 0, bytData.Length);
            m_fileRW.Flush();
            return bytData.Length;
        }

        public UInt64 GetLastRecordSeq()
        {
            return m_head.piAxuRecordsInfo.lluStart;
        }

        //要约定一次测试的BMS历史数据长度不变，要么没有，要么相同长度，否则DA读取肯定出错。
        public UInt32 WriteBdfRecord(List<SingleHisDfData> rList, Hashtable bmsTable)
        {
            if (rList.Count == 0)
                return 0;

            m_fileRW.Seek((long)m_head.piLogsInfo.lluStart, SeekOrigin.Begin);  //日志的开始就是记录数据的结尾
            foreach (SingleHisDfData item in rList)
            {
                bool bInitRecordLen = m_head.piAxuRecordsInfo.lluLen > 0;   //记录数据长度是否初始化
                byte[] bytData = RawSerialize(item);
                m_fileRW.Write(bytData, 0, bytData.Length);
                m_head.piRecordsInfo.lluLen += (UInt64)bytData.Length;
                if (!bInitRecordLen)
                    m_head.piAxuRecordsInfo.lluLen = (UInt64)bytData.Length;

                if (bmsTable.Count > 0)
                {
                    BmsHisData stBms = bmsTable[item.dwTestSn] as BmsHisData;
                    m_fileRW.WriteByte(stBms.Flag);

                    byte[] bytes = BitConverter.GetBytes(stBms.StDataCount);
                    m_fileRW.Write(bytes, 0, bytes.Length);
                    bytes = BitConverter.GetBytes(stBms.VolCount);
                    m_fileRW.Write(bytes, 0, bytes.Length);
                    bytes = BitConverter.GetBytes(stBms.TempCount);
                    m_fileRW.Write(bytes, 0, bytes.Length);
                    bytes = BitConverter.GetBytes(stBms.SelfCount);
                    m_fileRW.Write(bytes, 0, bytes.Length);
                    m_head.piRecordsInfo.lluLen += (1 + 2 * 4);
                    if (!bInitRecordLen)
                        m_head.piAxuRecordsInfo.lluLen += (1 + 2 * 4);

                    if (stBms.StDataCount > 0)
                    {
                        m_fileRW.Write(stBms.StData, 0, stBms.StData.Length);
                        m_head.piRecordsInfo.lluLen += (UInt64)stBms.StData.Length;
                        if (!bInitRecordLen)
                            m_head.piAxuRecordsInfo.lluLen += (UInt64)stBms.StData.Length;
                    }
                    if (stBms.VolCount > 0)
                    {
                        m_fileRW.Write(stBms.VolData, 0, stBms.VolData.Length);
                        m_head.piRecordsInfo.lluLen += (UInt64)stBms.VolData.Length;
                        if (!bInitRecordLen)
                            m_head.piAxuRecordsInfo.lluLen += (UInt64)stBms.VolData.Length;
                    }
                    if (stBms.TempCount > 0)
                    {
                        m_fileRW.Write(stBms.TempData, 0, stBms.TempData.Length);
                        m_head.piRecordsInfo.lluLen += (UInt64)stBms.TempData.Length;
                        if (!bInitRecordLen)
                            m_head.piAxuRecordsInfo.lluLen += (UInt64)stBms.TempData.Length;
                    }
                    if (stBms.SelfCount > 0)
                    {
                        m_fileRW.Write(stBms.SelfData, 0, stBms.SelfData.Length);
                        m_head.piRecordsInfo.lluLen += (UInt64)stBms.SelfData.Length;
                        if (!bInitRecordLen)
                            m_head.piAxuRecordsInfo.lluLen += (UInt64)stBms.SelfData.Length;
                    }
                }
                else
                {
                    byte bt = 0;
                    m_fileRW.WriteByte(bt);
                    m_head.piRecordsInfo.lluLen += 1;
                    if (!bInitRecordLen)
                        m_head.piAxuRecordsInfo.lluLen += 1;
                }
            }

            m_head.piAxuRecordsInfo.lluStart = rList[rList.Count - 1].dwTestSn;
            WriteHead();
            m_fileRW.Flush();
            if (m_head.piRecordsInfo.lluLen% m_head.piAxuRecordsInfo.lluLen != 0)
            {
                MsgUtil.WriteLog("记录数据长度有异常：总长度" + m_head.piRecordsInfo.lluLen.ToString() + " 单条长度" + m_head.piAxuRecordsInfo.lluLen.ToString());
            }
            return rList[rList.Count - 1].dwTestSn;
        }

        //写通道日志
        public int WriteTestLog(List<SingleHisLogData> listLog)
        {
            m_nLogCount = listLog.Count;
            m_fileRW.Seek((long)m_head.piLogsInfo.lluStart, SeekOrigin.Begin);
            foreach (SingleHisLogData item in listLog)
            {
                byte[] bytData = RawSerialize(item);
                m_fileRW.Write(bytData, 0, bytData.Length);
            }

            WriteHead();
            m_fileRW.Flush();
            return 0;
        }

        //写通道日志
        public int WriteStepStatis(List<STEP_STATIS> listStep)
        {
            m_fileRW.Seek((long)m_head.piStepsInfo.lluStart, SeekOrigin.Begin);
            MsgUtil.WriteLog("写工步统计信息：" + m_head.piStepsInfo.lluStart.ToString());
            foreach (STEP_STATIS item in listStep)
            {
                byte[] bytData = RawSerialize(item);
                m_fileRW.Write(bytData, 0, bytData.Length);
                m_head.piStepsInfo.lluLen += (UInt64)bytData.Length;
            }

            WriteHead();
            //m_fileRW.Flush();
            return 0;
        }

        public void Finish()
        {
            MsgUtil.WriteLog("文件信息：" + ToString());
            m_fileRW.Close();
        }

        public override string ToString()
        {
            return base.ToString()+ " ChannelInfo " + m_head.piChannelInfo.lluStart.ToString() + " "
                + m_head.piChannelInfo.lluLen.ToString()+ " StepsData "+ m_head.piStepsData.lluStart.ToString()
                + " " + m_head.piStepsData.lluLen.ToString()+ " RecordsInfo "+ m_head.piRecordsInfo.lluStart.ToString()
                +" " + m_head.piRecordsInfo.lluLen.ToString()+ " StepsInfo "+ m_head.piStepsInfo.lluStart.ToString()
                 + " " + m_head.piRecordsInfo.lluLen.ToString() + " StepsInfo " + m_head.piStepsInfo.lluStart.ToString()
                + " "+ m_head.piStepsInfo.lluLen.ToString() + " " + m_fileRW.Length.ToString();
        }
        //从文件计算工步统计信息
        public void CalcStepStatis(ref List<STEP_STATIS> sList)
        {
            UInt64 recordBegin = m_head.piRecordsInfo.lluStart;
            UInt32 recordCount = 0; //DA文件中几条记录数据
            if (sList.Count > 0)
                recordCount = sList[sList.Count - 1].dwLastRecordIndex;

            recordBegin += recordCount * m_head.piAxuRecordsInfo.lluLen;    

            //UInt32 nPreCycleId = 0;
            UInt32 nPreStepId = 0;
            UInt32 nStepType = 0;
            //sList.Add(step);
            STEP_STATIS stepN = new STEP_STATIS();
            while (recordBegin < (UInt64)(m_head.piRecordsInfo.lluStart+ m_head.piRecordsInfo.lluLen))
            {
                SingleHisDfData df = new SingleHisDfData();
                byte[] bytData = new byte[Marshal.SizeOf(df)];
                m_fileRW.Seek((long)recordBegin, SeekOrigin.Begin);
                m_fileRW.Read(bytData, 0, Marshal.SizeOf(df));
                recordBegin += m_head.piAxuRecordsInfo.lluLen;
                df = (SingleHisDfData)RawDeserialize(bytData, typeof(SingleHisDfData));
                if (/*df.dwCycle != nPreCycleId ||*/ df.stepID != nPreStepId || df.btStepType != nStepType)  //--产生了新的工步
                {
                    MsgUtil.WriteLog("记录数据的工步分隔处：" + m_fileRW.Position.ToString()+ " 记录结尾"+ 
                        (m_head.piRecordsInfo.lluStart + m_head.piRecordsInfo.lluLen).ToString());
                    //STEP_STATIS stepN = new STEP_STATIS();
                    if (stepN.btStepType > 0)
                    {
                        sList.Add(stepN);
                        stepN = new STEP_STATIS();
                    }
                    stepN.nRecordsCount++;
                    stepN.dwFirstRecordIndex = recordCount;
                    stepN.dwCycleID = df.dwCycle;
                    stepN.btStepType = df.btStepType;
                    stepN.dTmpStart = df.nTempature * DaFileElement.SCALE_TR;
                    //stepN.dTmpEnd = df.nTempature * DaFileElement.SCALE_TR;
                    stepN.dVolStart = df.nVolt * DaFileElement.SCALE_IU;
                    stepN.dCapEnd = df.nCap * DaFileElement.SCALE_CN;
                    stepN.dEng = df.nEngSum * DaFileElement.SCALE_CN;
                    stepN.dwStepID = (UInt32)sList.Count;
                   
                }
                else
                {
                    //STEP_STATIS stepN = sList[sList.Count - 1];
                    stepN.nRecordsCount++;
                    stepN.dwLastRecordIndex = recordCount;
                    //stepN.dTmpEnd = recordCount;
                    stepN.dTmpEnd = df.nTempature * DaFileElement.SCALE_TR;
                    stepN.dVolEnd = df.nVolt * DaFileElement.SCALE_IU;
                    stepN.dCap += df.nCap * DaFileElement.SCALE_CN - stepN.dCapEnd;
                    stepN.dCapEnd = df.nCap * DaFileElement.SCALE_CN;

                    stepN.dEng = df.nEngSum * DaFileElement.SCALE_CN;
                    stepN.dwTimeSection = df.stepTime;
                }

                nPreStepId = df.stepID;
                nStepType = df.btStepType;
                recordCount++;
            }

            sList.Add(stepN);
        }
    }
}
